'''
Created on 2011-5-23

@author: elm
'''

from ddbms.SqlStatement import FieldRef,TableRef

class Column:
    id = 0
    name = None
    table = 0
    type = None
    length = -1

class Site:
    id = 0
    name = None
    connection = 0
    segments = []
    
class Table:
    id = 0
    name = None
    columns = []
    primaryKey = 0
    segmentation = None
    '''
    can be Segment.Horizontal or Segment.Vertical    
    '''    
    segments = []
    
class Segment:
    Horizontal = -1
    Vertical = -2
    id = 0
    table = 0
    columns = []  
    sibling = 0
    name = None
    'Stores the next segment in same table'
    sites = []
    length = None

class HorizontalSegment(Segment):
    segmentCondition = None
    
class VerticalSegment(Segment):
    columns = []
    
class Schema(object):
    '''
    this class is a global dictionary for the logical database
    '''
    siteId = 0
    
    sites = {}
    
    tables = {}
    
    columns = {}
    
    segments = {}
    
    def __init__(self):
        '''
        Constructor
        '''     
        
    def toTableRef(self,table):
        if not isinstance(table,Table):
            table = self.findTable(table)
            if table == None:
                return None
        return TableRef(table.name)
    
    def toFieldRef(self,column,opt=None):
        '''
        convert Column instance to FieldRef instance
        
        toFieldRef(Column): 
            if Column instance is given, return FieldRef corresponds to Column
        toFieldRef(table,column):
            if other type are given, it will try to call 
            findColumn() with given parameters first,
            and transform its return value to a FieldRef        
        '''
        if not isinstance(column,Column):
            column = self.findColumn(column,opt)
        table = self.findTable(column.table)
        return FieldRef(self.toTableRef(table),column.name)
    
    def findColumn(self,table,key=None):
        '''
        findColumn(key)
            type(key) = Column: just return key
            type(key) = FieldRef: find Column instance correspond to key
            type(key) = int: find Column with given id
            type(key) = string: find Column with given name
                                (if many columns have a same name,
                                 you cannot predict which can be returned)
                                 
        findColumn(table,key)
            table: Table or any type that findTable() accepts
            key: int, string
            find column in given table with given id or name            
        '''
        if key == None:
            if isinstance(table,FieldRef):
                return self.findColumn(table.table.table,table.column)
            else:
                for k in self.columns:                    
                    if k==table or (self.columns[k]!=None and self.columns[k].name.lower()==str(table).lower()):
                        return self.columns[k]
        else:
            if isinstance(table,Table):
                table = table.id
            else:
                table = self.findTable(table).id
            for k in self.columns:
                if(k==key or (self.columns[k]!=None and self.columns[k].name.lower()==str(key).lower())):
                    col = self.columns[k]
                    if col.table == table:
                        return self.columns[k]       
    
    def findTable(self,key):
        '''
        findTable(key)
            type(key) = Table: just return key
            type(key) = TableRef: return Table corresponds to key
            type(key) = string: return Table with given name
            type(key) = int: return Table with given id
        '''
        if isinstance(key,Table):
            return key
        if isinstance(key,TableRef):
            key = key.table
        for k in self.tables:
            if(k==key or (self.tables[k]!=None and self.tables[k].name.lower()==str(key).lower())):
                return self.tables[k]
    
    def findSite(self,site):
        if isinstance(site,Site):
            return site
        if site in self.sites:
            return self.sites[site]
        return None
    
    def findSegment(self,key):
        for k in self.segments:
            if(k==key):
                return self.segments[k]
    
    def finSegmentSite(self,seg):
        if not isinstance(seg,Segment):
            seg = self.findSegment(seg)
        sites = []
        for siteId in self.sites:
            site = self.sites[siteId]
            if site==None:
                continue
            for segId in site.segments:
                if segId == seg.id:
                    sites.append(siteId)
                    break
        return sites
    
    def listSegments(self):
        res=[]
        for k in self.segments:
            if(k>0):
                res+=[self.segments[k]]
        return res;        
    
    def __str__(self):
        str = "My Site ID: %d\n"%self.siteId
        for tid in self.tables:
            table = self.tables[tid]
            if table == None:
                continue
            str += "[%d]%s: "%(table.id,table.name)
            for cid in table.columns:
                col = self.columns[cid]
                str += "[%d]%s "%(col.id,col.name)
            str+="\n"
            for sid in table.segments:
                seg = self.segments[sid]
                sites = ", ".join("s%d"% id for id in self.finSegmentSite(seg))
                if table.segmentation == Segment.Horizontal:                    
                    str+="    [[%d]%s on %s]H: %s\n"%(seg.id,seg.name,sites,seg.segmentCondition)
                elif table.segmentation == Segment.Vertical:
                    str+="    [[%d]%s on %s]V: "%(seg.id,seg.name,sites)
                    for cid in seg.columns:
                        col = self.columns[cid]
                        str += "[%d]%s "%(col.id,col.name)
                    str += "\n"
        return str
